package yslai.divination;

import java.io.*;
import java.util.*;

public class DivinationRound {
	private Gua origin;
	private Gua mutation;
	private int mut_count = 0;
	private Properties prop;
	private boolean hasMutation = false;
	
	private int mutate_bit = 0;
	
	private String result_name;
	private String result_txt;
	private String result_desc;
	
	private String jen_name;
	private String jen_txt;
	private String jen_desc;
	
	private String hue_name;
	private String hue_txt;
	private String hue_desc;
	
	public DivinationRound(){
		prop = new Properties();
		try {
			prop.load(DivinationRound.class.getResourceAsStream("/assets/explanation.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		// Get originGua
		int[] origin_yao = new int[6];
		for(int i = 0 ; i < origin_yao.length ; i++){
			origin_yao[i] = generateYao();
		}
		
		// conpute mutate
		int[] mutate_yao = new int[6];
		for(int i = 0 ; i < origin_yao.length ; i++){
			if(origin_yao[i] == 6){
				mut_count ++;
				mutate_yao[i] = 9;
				mutate_bit = mutate_bit | (int)Math.pow(2, i);
			}else if(origin_yao[i] == 9){
				mut_count ++;
				mutate_yao[i] = 6;
				mutate_bit = mutate_bit | (int)Math.pow(2, i);
			}else{
				mutate_yao[i] = origin_yao[i];
			}
		}
		
		String origin_yaolist = Integer.toString(origin_yao[0]%2)+Integer.toString(origin_yao[1]%2)+Integer.toString(origin_yao[2]%2)+Integer.toString(origin_yao[3]%2)+Integer.toString(origin_yao[4]%2)+Integer.toString(origin_yao[5]%2);
		origin = new Gua(origin_yaolist, origin_yao);
		if(mut_count>0){
			hasMutation = true;
			String mutate_yaolist = Integer.toString(mutate_yao[0]%2)+Integer.toString(mutate_yao[1]%2)+Integer.toString(mutate_yao[2]%2)+Integer.toString(mutate_yao[3]%2)+Integer.toString(mutate_yao[4]%2)+Integer.toString(mutate_yao[5]%2);
			mutation = new Gua(mutate_yaolist, mutate_yao);
			
			switch(mut_count){
			case 1:
				int bit = (int)(Math.log(mutate_bit) / Math.log(2));
				result_name = "以"+origin.getName()+"卦 "+prop.getProperty("divination.count."+bit)+"爻爻辭為斷";
				result_txt = "爻辭："+origin.getYao_txt(bit);
				result_desc = "※說明："+origin.getYao_desc(bit);
				break;
			case 2:
				int highbit = (int)(Math.log(mutate_bit) / Math.log(2));
				int lowbit = (int)(Math.log(mutate_bit-Math.pow(2, highbit)) / Math.log(2));				
				hue_name = "以本卦"+origin.getName()+"卦變之上爻 "+prop.getProperty("divination.count."+highbit)+"爻爻辭為悔（評斷）";
				hue_txt = "爻辭："+origin.getYao_txt(highbit);
				hue_desc = "※說明："+origin.getYao_desc(highbit);
				jen_name = "以本卦"+origin.getName()+"卦變之下爻 "+prop.getProperty("divination.count."+lowbit)+"爻爻辭為貞（參考）";
				jen_txt = "爻辭："+origin.getYao_txt(lowbit);
				jen_desc = "※說明："+origin.getYao_desc(lowbit);				
				break;
			case 3:
				hue_name = "變卦："+mutation.getName()+"卦為悔（評斷）";
				hue_txt = "卦辭："+mutation.getGua_txt();
				hue_desc = "※說明："+mutation.getGua_desc();
				jen_name = "本卦："+origin.getName()+"卦為貞（參考）";
				jen_txt = "卦辭："+origin.getGua_txt();
				jen_desc = "※說明："+origin.getGua_desc();
				break;
			case 4:
				mutate_bit = mutate_bit ^ 63;
				int mhighbit = (int)(Math.log(mutate_bit) / Math.log(2));
				int mlowbit = (int)(Math.log(mutate_bit-Math.pow(2, mhighbit)) / Math.log(2));
				hue_name = "以變卦"+mutation.getName()+"卦變之下爻 "+prop.getProperty("divination.count."+mlowbit)+"爻爻辭為悔（評斷）";
				hue_txt = "爻辭："+mutation.getYao_txt(mlowbit);
				hue_desc = "※說明："+mutation.getYao_desc(mlowbit);
				jen_name = "以變卦"+mutation.getName()+"卦變之上爻 "+prop.getProperty("divination.count."+mhighbit)+"爻爻辭為貞（參考）";
				jen_txt = "爻辭："+mutation.getYao_txt(mhighbit);
				jen_desc = "※說明："+mutation.getYao_desc(mhighbit);
				break;
			case 5:
				mutate_bit = mutate_bit ^ 63;
				result_name = "以"+mutation.getName()+"卦 "+prop.getProperty("divination.count."+mutate_bit)+"爻爻辭為斷";
				result_txt = "爻辭："+mutation.getYao_txt(mutate_bit);
				result_desc = "※說明："+mutation.getYao_desc(mutate_bit);
				break;
			case 6:
				if(origin_yaolist.equals("000000")){
					result_name = "以坤卦用六為斷";
					result_txt = "卦辭："+prop.getProperty("divination.txt.6");
					result_desc = "※說明："+prop.getProperty("divination.desc.6");
				}else if(origin_yaolist.equals("111111")){
					result_name = "以乾卦用九為斷";
					result_txt = "卦辭："+prop.getProperty("divination.txt.9");
					result_desc = "※說明："+prop.getProperty("divination.desc.9");
				}else{
					result_name = "以"+mutation.getName()+"卦卦辭為斷";
					result_txt = "卦辭："+mutation.getGua_txt();
					result_desc = "※說明："+mutation.getGua_desc();
				}
				break;
			}
			
		}else{
			/* determine result */
			result_name = "以"+origin.getName()+"卦卦辭為斷";
			result_txt = "卦辭："+origin.getGua_txt();
			result_desc = "※說明："+origin.getGua_desc();
		}
	}
	
	public String getResult_name() {
		return result_name;
	}


	public String getResult_txt() {
		return result_txt;
	}


	public String getResult_desc() {
		return result_desc;
	}


	public String getJen_name() {
		return jen_name;
	}


	public String getJen_txt() {
		return jen_txt;
	}


	public String getJen_desc() {
		return jen_desc;
	}


	public String getHue_name() {
		return hue_name;
	}


	public String getHue_txt() {
		return hue_txt;
	}


	public String getHue_desc() {
		return hue_desc;
	}


	public Gua getOrigin() {
		return origin;
	}


	public Gua getMutation() {
		return mutation;
	}


	public int getMut_count() {
		return mut_count;
	}


	public boolean isHasMutation() {
		return hasMutation;
	}


	private int generateYao(){
		int chien = 50;
		chien -= 1;		
		// round 1,2,3
		chien = rollChien(chien);
		chien = rollChien(chien);
		chien = rollChien(chien);
		return chien/4;
	}
	
	private int rollChien(int chien){
		int r_left = (int)(Math.random()*(chien-1))+1;
		int r_right = chien - r_left;
		if(r_left > 1){
			r_left -= 1;
		}else{
			r_right -= 1;
		}
		
		r_left = r_left%4==0 ? r_left-4 : r_left-(r_left%4);
		r_right = r_right%4==0 ? r_right-4 : r_right-(r_right%4);
		return r_left + r_right;
	}

	public class Gua{
		private String name;
		private String id;
		private int[] yao = new int[6];
		private int[] origin_yao = new int[6];
		
		private String gua_txt;
		private String gua_desc;
		
		private String[] yao_txt = new String[6];
		private String[] yao_desc = new String[6];
		
		Gua(String name, int[] yao){
			this.id = name;
			this.name = prop.getProperty("divination.name."+name);
			this.origin_yao = yao;
			this.yao = new int[]{origin_yao[0]%2,origin_yao[1]%2,origin_yao[2]%2,origin_yao[3]%2,origin_yao[4]%2,origin_yao[5]%2};
			
			this.gua_txt = prop.getProperty("divination.txt."+name);
			this.gua_desc = prop.getProperty("divination.desc."+name);
			
			for(int i = 0 ; i < 6 ; i++){
				yao_txt[i] = prop.getProperty("divination.yaotxt."+name+"."+i);
				yao_desc[i] = prop.getProperty("divination.yaodesc."+name+"."+i);
			}
			
		}
		
		public String getGua_txt() {
			return gua_txt;
		}


		public String getGua_desc() {
			return gua_desc;
		}


		public String getYao_txt(int idx) {
			return yao_txt[idx];
		}


		public String getYao_desc(int idx) {
			return yao_desc[idx];
		}


		public String getdebug_yao(){
			return "["+origin_yao[0]+origin_yao[1]+origin_yao[2]+origin_yao[3]+origin_yao[4]+origin_yao[5]+"]";
		}

		public String getId() {
			return id;
		}

		public int[] getOrigin_yao() {
			return origin_yao;
		}


		public String getName() {
			return name;
		}

		public int[] getYao() {
			return yao;
		}
		
	}
}
